
// import oimo.m.Vec3;
// import oimo.m.M;
// import oimo.common.Vec3;
// import oimo.collision.raycast.*;

import { Vec3 } from "../../common/Vec3";

/**
 * The axis-aligned bounding box.
 */
export class Aabb {
	_min: Vec3;
	_max: Vec3;

	/**
	 * Creates an empty AABB. Minimum and maximum points are set to zero.
	 */
	constructor() {
		this._min = new Vec3();
		this._max = new Vec3();
	}

	/**
	 * Sets the minimum and maximum point and returns `this`.
	 *
	 * Equivallent to `setMin(min).setMax(max)`.
	 */
	public init(min: Vec3, max: Vec3): Aabb {
		this._min.copyFrom(min);
		this._max.copyFrom(max);
		return this;
	}

	/**
	 * Returns the minimum point of the axis-aligned bounding box.
	 */
	public getMin(): Vec3 {
		return this._min.clone();
	}

	/**
	 * Sets the minimum point of the axis-aligned bounding box to `min`.
	 *
	 * This does not create a new instance of `Vec3`.
	 */
	public getMinTo(min: Vec3): void {
		min.copyFrom(this._min);
	}

	/**
	 * Sets the minimum point of the axis-aligned bounding box to `min` and returns `this`.
	 */
	public setMin(min: Vec3): Aabb {
		this._min.copyFrom(min);
		return this;
	}

	/**
	 * Returns the maximum point of the axis-aligned bounding box.
	 */
	public getMax(): Vec3 {
		return this._max.clone();
	}

	/**
	 * Sets the maximum point of the axis-aligned bounding box to `max`.
	 *
	 * This does not create a new instance of `Vec3`.
	 */
	public getMaxTo(max: Vec3): void {
		max.copyFrom(this._max);
	}

	/**
	 * Sets the maximum point of the axis-aligned bounding box to `max` and returns `this`.
	 */
	public setMax(max: Vec3): Aabb {
		this._max.copyFrom(max);
		return this;
	}

	/**
	 * Returns the center of the AABB.
	 */
	public getCenter(): Vec3 {
		let c = this._min.add(this._max);
		c.scaleEq(0.5);
		return c;
	}

	/**
	 * Sets `center` to the center of the AABB.
	 *
	 * This does not create a new instance of `Vec3`.
	 */
	public getCenterTo(center: Vec3): void {
		center.copyFrom(this._min)
		center.addEq(this._max);
		center.scaleEq(0.5);
	}

	/**
	 * Returns the half extents of the AABB.
	 */
	public getExtents(): Vec3 {
		let c = this._max.clone();
		c.subEq(this._min);
		c.scaleEq(0.5);
		return c;
	}

	/**
	 * Sets `halfExtents` to the half extents of the AABB.
	 *
	 * This does not create a new instance of `Vec3`.
	 */
	public getExtentsTo(halfExtents: Vec3): void {
		halfExtents.copyFrom(this._max);
		halfExtents.subEq(this._min);
		halfExtents.scaleEq(0.5);
	}

	/**
	 * Combines `other` into this AABB and returns `this`.
	 */
	public combine(other: Aabb): Aabb {
		this._min.minEq(other._min);
		this._max.minEq(this._max);
		return this;
	}

	/**
	 * Returns the combined aabb of `this` and `other` with new.
	 */
	public combined(other: Aabb): Aabb {
		var aabb: Aabb = this.clone();
		aabb.combine(other);
		return aabb;
	}

	/**
	 * Returns whether `this` and `other` intersect.
	 */
	public overlap(other: Aabb): boolean {
		let mi1 = this._min;
		let ma1 = this._max;
		let mi2 = other._min;
		let ma2 = other._max;
		return mi1.x < ma2.x && ma1.x > mi2.x
			&& mi1.y < ma2.y && ma1.y > mi2.y
			&& mi1.z < ma2.z && ma1.z > mi2.z;
	}

	/**
	 * Returns the intersection of `this` and `other`.
	 */
	public getnumberersection(other: Aabb): Aabb {
		var aabb: Aabb = new Aabb();
		this.getnumberersectionTo(other, aabb);
		return aabb;
	}

	/**
	 * Sets `intersection` to the intersection of `this` and `other`.
	 *
	 * This does not create a new instance of `Aabb`.
	 */
	public getnumberersectionTo(other: Aabb, intersection: Aabb): void {
		intersection.copyFrom(this);
		intersection._min.maxEq(other._min);
		intersection._max.minEq(other._max);
	}

	/**
	 * Copies AABB from `aabb` to and returns `this`.
	 */
	public copyFrom(aabb: Aabb): Aabb {
		this._min.copyFrom(aabb._min);
		this._max.copyFrom(aabb._max);
		return this;
	}

	/**
	 * Returns a clone of the AABB.
	 */
	public clone(): Aabb {
		let aabb: Aabb = new Aabb();
		aabb.copyFrom(this);
		return aabb;
	}

}
